import 'package:flutter/material.dart';

enum CustomButtonTitleImagePosition{
  onlyTitle,
  onlyImage,
  titleLeftImageRight,
  imageLeftTitleRight,
  titleTopImageBottom,
  imageTopTitleBottom;
}
enum CustomButtonContentAlignment{
  center(0),
  left(1),
  right(2),
  top(4),
  bottom(8),
  between(16); //title和image spaceBetween
  final int value;
  const CustomButtonContentAlignment(this.value);
}
///撑开模式
enum CustomButtonContentStretch{
  none(0),
  horizontal(1),//水平方向没有width的时候起作用
  vertical(2),//垂直方向没有height的时候起作用
  all(3);
  final int value;
  const CustomButtonContentStretch(this.value);
}
class CustomButton extends StatefulWidget {
  double? width, height;

  bool isEnabled;
  bool isSelected;
  bool isHighlighted;

  late  CustomButtonTitleImagePosition positionType;
  final CustomButtonContentAlignment contentAlignment;
  final double space; //title 和image间距
  final EdgeInsets margin;
  final double hPadding;//对齐方式下有效 内边距
  final double vPadding;//对齐方式下有效 内边距
  /**
   * ltPadding between模式下起作用
   * left Or Top Padding
   */
  final double ltPadding;
  /**
   * rbPadding between模式下起作用
   * right Or Bottom Padding
   */
  final double rbPadding;

  CustomButtonContentStretch contentStretch;
  ///撑开模式下的padding
  EdgeInsets stretchPadding;
  /*title*/
  String title;
  String? _normalTitle;
  final String? selectedTitle;
  final String? highlightedTitle;
  final String? disabledTitle;

  /*title color*/
  Color titleColor;
  Color? _normalTitleColor;
  final Color? selectedTitleColor;
  final Color? highlightedTitleColor;
  final Color? disabledTitleColor;

  /*font*/
  FontWeight? fontWeight;
  double fontSize;
  double? _normalFontSize;
  final double? selectedFontSize;
  final double? highlightedFontSize;
  final double? disabledFontSize;

  /*image*/
  Image? image;
  Image? _normalImage;
  final Image? selectedImage;
  final Image? highlightedImage;
  final Image? disabledImage;

  /*backgroundColor*/
  Color backgroundColor;
  Color? _normalBgColor;
  final Color? selectedBgColor;
  final Color? highlightedBgColor;
  final Color? disabledBgColor;

  /*Border color*/
  Color? borderColor;
  Color? _normalBorderColor;
  final Color? highlightedBorderColor;
  final Color? selectedBorderColor;
  final Color? disabledBorderColor;

  final double borderWidth;

  final BorderRadiusGeometry? borderRadius;

   int titleMaxLength;
  final Function(BuildContext context, CustomButton btn)? onPressed;
  CustomButton({
    Key? key,
    this.width,
    this.height,
    this.isEnabled = true,
    this.isSelected = false,
    this.isHighlighted = false,
    this.positionType = CustomButtonTitleImagePosition.imageLeftTitleRight,
    this.contentAlignment = CustomButtonContentAlignment.center,
    this.space = 5,
    this.margin = EdgeInsets.zero,
    this.hPadding = 0,
    this.vPadding = 0,
    this.ltPadding = 0,
    this.rbPadding = 0,
    this.contentStretch = CustomButtonContentStretch.none,
    this.stretchPadding = const EdgeInsets.only(),
    this.title = '',
    this.selectedTitle,
    this.highlightedTitle,
    this.disabledTitle,
    this.titleColor = Colors.white,
    this.selectedTitleColor,
    this.highlightedTitleColor,
    this.disabledTitleColor,

    this.fontWeight,
    this.fontSize = 16,
    this.selectedFontSize,
    this.highlightedFontSize,
    this.disabledFontSize,

    this.image,
    this.selectedImage,
    this.highlightedImage,
    this.disabledImage,

    this.backgroundColor = const Color.fromRGBO(30, 124, 240, 0),
    this.selectedBgColor,
    this.highlightedBgColor,
    this.disabledBgColor,

    this.borderColor,
    this.highlightedBorderColor,
    this.selectedBorderColor,
    this.disabledBorderColor,
    this.borderWidth = 0,

    this.borderRadius,

    this.titleMaxLength = 100,
    this.onPressed,

  }) : super(key: key){
    _normalTitle = title;
    _normalTitleColor = titleColor;
    _normalFontSize = fontSize;
    _normalImage = image;
    _normalBgColor = backgroundColor;
    _normalBorderColor = borderColor;

    if(_normalTitle!.isNotEmpty && _normalImage == null){
      positionType = CustomButtonTitleImagePosition.onlyTitle;
    }else if(_normalTitle!.isEmpty && _normalImage != null){
      positionType = CustomButtonTitleImagePosition.onlyImage;
    }

    if((width == null || width == 0) &&(height == null || height == 0)){
      contentStretch = CustomButtonContentStretch.all;
    }else if(width == null || width == 0) {
      contentStretch = CustomButtonContentStretch.horizontal;
    }else if(height == null || height == 0) {
      contentStretch = CustomButtonContentStretch.vertical;
    }else{
      contentStretch = CustomButtonContentStretch.none;
    }

    setSelectedState();
    setEnabledState();

  }

  set highlighted(bool h){
    isHighlighted = h;
    title = isHighlighted ? (highlightedTitle ?? _normalTitle!) : _normalTitle!;
    title = title.length > titleMaxLength ? ("${title.substring(0,titleMaxLength)}...") : title;
    titleColor = isHighlighted ? (highlightedTitleColor ?? _normalTitleColor!) : _normalTitleColor!;
    fontSize = isHighlighted ? highlightedFontSize ?? _normalFontSize! : _normalFontSize!;
    image = isHighlighted ? (highlightedImage ?? _normalImage) :_normalImage ;
    backgroundColor = isHighlighted ? (highlightedBgColor ?? _normalBgColor!) : _normalBgColor!;
    borderColor = isHighlighted ? (highlightedBorderColor ??
        _normalBorderColor)  : _normalBorderColor;
  }

  bool get highlighted{
    return isHighlighted;
  }
  void setSelectedState(){
    title = isSelected ? selectedTitle ?? _normalTitle! : _normalTitle!;
    title = title.length > titleMaxLength ? ("${title.substring(0,titleMaxLength)}...") : title;
    titleColor = isSelected ? selectedTitleColor ?? _normalTitleColor! : _normalTitleColor!;
    fontSize = isSelected ? selectedFontSize ?? _normalFontSize! : _normalFontSize!;
    image = isSelected ? selectedImage ?? _normalImage : _normalImage;
    backgroundColor = isSelected ? selectedBgColor ?? _normalBgColor! :  _normalBgColor!;
    borderColor = isSelected ? selectedBorderColor ?? _normalBorderColor  : _normalBorderColor;
  }
  set selected(bool sel){
    isSelected = sel;
    setSelectedState();
  }

  bool get selected{
    return isSelected;
  }

  bool get enabled{
    return isEnabled;
  }

  setEnabledState(){
    if(!isEnabled){
      if(disabledTitle != null) title = disabledTitle!;
      title = title.length > titleMaxLength ? ("${title.substring(0,titleMaxLength)}...") : title;
      if(disabledTitleColor != null) titleColor = disabledTitleColor!;
      if(disabledTitleColor != null) titleColor = disabledTitleColor!;
      if(disabledFontSize != null) fontSize = disabledFontSize!;
      if(disabledImage != null) image = disabledImage!;
      if(disabledBgColor != null) backgroundColor = disabledBgColor!;
      if(disabledBorderColor != null) borderColor = disabledBorderColor!;
    }else{
      if(isSelected){
        selected = true;
      }else{
        highlighted = isHighlighted;
      }
    }
  }
  set enabled(bool en){
     isEnabled = en;
     setEnabledState();
  }
  @override
  State<CustomButton> createState() => _CustomButtonState();
}

class _CustomButtonState extends State<CustomButton> with WidgetsBindingObserver {

  bool isEnabled = false;
  bool isSelected = false;
  bool isHighlighted = false;
  @override void didUpdateWidget(CustomButton oldWidget)
  {
    super.didUpdateWidget(oldWidget);

  }
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _resetState();

  }

  _resetState(){
    if(!widget.isEnabled){
      if(widget.disabledTitle != null) widget.title = widget.disabledTitle!;
      widget.title = widget.title.length > widget.titleMaxLength ? ("${widget.title.substring(0,widget.titleMaxLength)}...") : widget.title;
      if(widget.disabledTitleColor != null) widget.titleColor = widget.disabledTitleColor!;
      if(widget.disabledTitleColor != null) widget.titleColor = widget.disabledTitleColor!;
      if(widget.disabledFontSize != null) widget.fontSize = widget.disabledFontSize!;
      if(widget.disabledImage != null) widget.image = widget.disabledImage!;
      if(widget.disabledBgColor != null) widget.backgroundColor = widget.disabledBgColor!;
      if(widget.disabledBorderColor != null) widget.borderColor = widget.disabledBorderColor!;

    }else{
      if(widget.isSelected){

        widget.title = widget.selectedTitle ?? widget._normalTitle!;
        widget.title = widget.title.length > widget.titleMaxLength ? ("${widget.title.substring(0,widget.titleMaxLength)}...") : widget.title;
        widget.titleColor = widget.selectedTitleColor ?? widget._normalTitleColor!;
        widget.fontSize = widget.selectedFontSize ?? widget._normalFontSize!;
        widget.image = widget.selectedImage ?? widget._normalImage;
        widget.backgroundColor = widget.selectedBgColor ?? widget._normalBgColor!;
        widget.borderColor = widget.selectedBorderColor ?? widget._normalBorderColor;
      }else{
        widget.title = widget.isHighlighted ? (widget.highlightedTitle ?? widget._normalTitle!) : widget._normalTitle!;
        widget.title = widget.title.length > widget.titleMaxLength ? ("${widget.title.substring(0,widget.titleMaxLength)}...") : widget.title;
        widget.titleColor = widget.isHighlighted ? (widget.highlightedTitleColor ?? widget._normalTitleColor!) : widget._normalTitleColor!;
        widget.fontSize = widget.isHighlighted ? widget.highlightedFontSize ?? widget._normalFontSize! : widget._normalFontSize!;
        widget.image = widget.isHighlighted ? (widget.highlightedImage ?? widget._normalImage) : widget._normalImage;
        widget.backgroundColor = widget.isHighlighted ? (widget.highlightedBgColor ?? widget._normalBgColor!) : widget._normalBgColor!;
        widget.borderColor = widget.isHighlighted ? (widget.highlightedBorderColor ??
            widget._normalBorderColor) : widget._normalBorderColor;
      }
    }
  }

  _getChild(){
    int hAlign = widget.contentAlignment.value &
    (CustomButtonContentAlignment.left.value | CustomButtonContentAlignment.left.value);
    int vAlgin = widget.contentAlignment.value &
    (CustomButtonContentAlignment.top.value | CustomButtonContentAlignment.bottom.value);

    Widget? child;
    /*between模式只用于同时有title和image的情况 并且排列方向有宽或高*/
    if((widget.contentAlignment == CustomButtonContentAlignment.between) &&
        (widget.positionType != CustomButtonTitleImagePosition.onlyTitle &&
            widget.positionType != CustomButtonTitleImagePosition.onlyImage) &&
        (widget.width != null || widget.height != null)
    ){


      child = Stack(
        children: [
          Positioned(
            width:(widget.positionType == CustomButtonTitleImagePosition.imageLeftTitleRight||
                widget.positionType == CustomButtonTitleImagePosition.titleLeftImageRight) ?
            widget.width! - widget.ltPadding - widget.rbPadding : widget.width,
            height: (widget.positionType == CustomButtonTitleImagePosition.imageTopTitleBottom||
                widget.positionType == CustomButtonTitleImagePosition.titleTopImageBottom) ?
            widget.height! - widget.ltPadding - widget.rbPadding : widget.height,
            left: (widget.positionType == CustomButtonTitleImagePosition.imageLeftTitleRight||
                widget.positionType == CustomButtonTitleImagePosition.titleLeftImageRight)?widget.ltPadding : null,
            top: (widget.positionType == CustomButtonTitleImagePosition.imageTopTitleBottom||
                widget.positionType == CustomButtonTitleImagePosition.titleTopImageBottom) ? widget.ltPadding : null,

            child: _getBetweenTitleAndImage(),
          ),
        ],
      );
    }else{

      child = Stack(
        alignment: AlignmentDirectional.center,
        children: [
          Positioned(
            left: (hAlign == CustomButtonContentAlignment.left.value) ? widget.hPadding : null,
            right: (hAlign == CustomButtonContentAlignment.right.value) ? widget.hPadding : null,
            top: (vAlgin == CustomButtonContentAlignment.top.value) ? widget.vPadding : null,
            bottom:(vAlgin == CustomButtonContentAlignment.bottom.value) ? widget.vPadding : null,
            child: _getTitleAndImage(),
          )
        ],
      );
    }
    return child;

  }

  _getBetweenTitleAndImage()
  {
    Widget? child;
    switch(widget.positionType){
      case CustomButtonTitleImagePosition.imageLeftTitleRight:
        child = Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            widget.image!,
            Text(widget.title,
              style: TextStyle(
                color: widget.titleColor,
                fontSize: widget.fontSize,
                fontWeight: widget.fontWeight,
              ) ,
            ),
          ],
        );
        break;
      case CustomButtonTitleImagePosition.titleLeftImageRight:
        child = Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(widget.title,
              style: TextStyle(
                color: widget.titleColor,
                fontSize: widget.fontSize,
                fontWeight: widget.fontWeight,
              ) ,
            ),
            widget.image!,
          ],
        );
        break;

      case CustomButtonTitleImagePosition.imageTopTitleBottom:
        child = Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            widget.image!,
            Text(widget.title,
              style: TextStyle(
                color: widget.titleColor,
                fontSize: widget.fontSize,
                fontWeight: widget.fontWeight,
              ) ,
            ),

          ],
        );
        break;

      case CustomButtonTitleImagePosition.titleTopImageBottom:
        child = Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(widget.title,
              style: TextStyle(
                color: widget.titleColor,
                fontSize: widget.fontSize,
                fontWeight: widget.fontWeight,
              ) ,
            ),
            widget.image!,
          ],
        );
        break;
      default:
        break;
    }
    return child;
  }
  _getTitleAndImage()
  {
    int hStretch = widget.contentStretch.value &  CustomButtonContentStretch.horizontal.value;
    int vStretch = widget.contentStretch.value &  CustomButtonContentStretch.vertical.value;
    double left = (hStretch == CustomButtonContentStretch.horizontal.value) ? widget.stretchPadding.left : 0;
    double right = (hStretch == CustomButtonContentStretch.horizontal.value) ? widget.stretchPadding.right : 0;
    double top = (vStretch == CustomButtonContentStretch.vertical.value) ? widget.stretchPadding.top : 0;
    double bottom = (vStretch == CustomButtonContentStretch.vertical.value) ? widget.stretchPadding.bottom : 0;
    Widget? child;
    switch(widget.positionType) {
      case CustomButtonTitleImagePosition.onlyTitle:

        child = Container(
           padding: EdgeInsets.fromLTRB(left, top, right, bottom),
          child: Text(widget.title,
            style: TextStyle(
              color: widget.titleColor,
              fontSize: widget.fontSize,
              fontWeight: widget.fontWeight,
            ) ,
          ),
        );
        break;
      case CustomButtonTitleImagePosition.onlyImage:
        child = Container(
          padding: EdgeInsets.fromLTRB(left, top, right, bottom),

          child:widget.image!,
        );
        break;
      case CustomButtonTitleImagePosition.imageLeftTitleRight:

        child = Container(
           padding: EdgeInsets.fromLTRB(left, top, right, bottom),

          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              widget.image!,
              SizedBox(width: widget.space,),
              Text(widget.title,
                style: TextStyle(
                  color: widget.titleColor,
                  fontSize: widget.fontSize,
                  fontWeight: widget.fontWeight,
                ) ,
              ),
            ],
          ),
        );
        break;

      case CustomButtonTitleImagePosition.titleLeftImageRight:
        child = Container(
           padding: EdgeInsets.fromLTRB(left, top, right, bottom),

          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(widget.title,
                style: TextStyle(
                  color: widget.titleColor,
                  fontSize: widget.fontSize,
                  fontWeight: widget.fontWeight,
                ) ,
              ),
              SizedBox(width: widget.space,),
              widget.image!,
            ],
          ),
        );
        break;

      case CustomButtonTitleImagePosition.imageTopTitleBottom:
        child = Container(
           padding: EdgeInsets.fromLTRB(left, top, right, bottom),

          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              widget.image!,
              SizedBox(height: widget.space,),
              Text(widget.title,
                style: TextStyle(
                  color: widget.titleColor,
                  fontSize: widget.fontSize,
                  fontWeight: widget.fontWeight,
                ) ,
              ),
            ],
          ),
        );
        break;

      case CustomButtonTitleImagePosition.titleTopImageBottom:
        child = Container(
           padding: EdgeInsets.fromLTRB(left, top, right, bottom),

          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(widget.title,
                style: TextStyle(
                  color: widget.titleColor,
                  fontSize: widget.fontSize,
                  fontWeight: widget.fontWeight,
                ) ,
              ),
              SizedBox(height: widget.space,),
              widget.image!,
            ],
          ),
        );
        break;
    }
    return child;
  }
  @override
  Widget build(BuildContext context) {

    return GestureDetector(
      onTap: (){
        if(!widget.isEnabled){
          return;
        }
        widget.highlighted = false;
        widget.selected = widget.isSelected;
        setState(() {

        });
        CustomButton btn = context.widget as CustomButton;
        widget.onPressed != null ? widget.onPressed!(context,btn) : null;
      },
      onTapDown: (TapDownDetails details){
        if(!widget.isEnabled){
          return;
        }
        widget.highlighted = true;
        setState(() {

        });
      },
      onTapCancel: (){
        if(!widget.isEnabled){
          return;
        }
        widget.highlighted = false;
        widget.selected = widget.isSelected;
        setState(() {

        });
      },
      child: Container(
        width: widget.width,
        height: widget.height,
        margin: widget.margin,
        decoration: BoxDecoration(
          color: widget.backgroundColor,
          border: Border.all(
            color: widget.borderColor ??  widget.backgroundColor,
            width: widget.borderWidth,
          ),
          borderRadius: widget.borderRadius,
        ),
        child: _getChild(),
      ),
    );
  }
}
